package org.dromara.iot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.iot.domain.IotElevatorRepair;
import org.dromara.iot.domain.bo.IotElevatorBo;
import org.dromara.iot.domain.bo.IotElevatorFaultBo;
import org.dromara.iot.domain.bo.IotElevatorRepairBo;
import org.dromara.iot.domain.bo.IotFaultRecordBo;
import org.dromara.iot.domain.vo.IotElevatorFaultVo;
import org.dromara.iot.domain.vo.IotElevatorRepairVo;
import org.dromara.iot.domain.vo.IotElevatorVo;
import org.dromara.iot.domain.vo.IotFaultRecordVo;
import org.dromara.iot.enums.BusinessCodeEnum;
import org.dromara.iot.enums.ElevatorStatusEnum;
import org.dromara.iot.enums.RepairStateEnum;
import org.dromara.iot.mapper.IotElevatorRepairMapper;
import org.dromara.iot.service.IIotElevatorFaultService;
import org.dromara.iot.service.IIotElevatorRepairService;
import org.dromara.iot.service.IIotElevatorService;
import org.dromara.system.service.ISysDictDataService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 电梯维修Service业务层处理
 *
 * @author lsl
 * @date 2024-06-15
 */
@RequiredArgsConstructor
@Service
public class IotElevatorRepairServiceImpl implements IIotElevatorRepairService {

    private final IotElevatorRepairMapper baseMapper;

    private final IotFaultRecordServiceImpl faultRecordService;

    private final ISysDictDataService dictDataService;

    private final IIotElevatorFaultService elevatorFaultService;

    private final IIotElevatorService elevatorService;

    /**
     * 查询电梯维修
     */
    @Override
    public IotElevatorRepairVo queryById(Long repairId) {
        IotElevatorRepairVo iotElevatorRepairVo = baseMapper.selectVoById(repairId);
        List<IotFaultRecordVo> recordVoList = faultRecordService.queryListByRepairId(repairId);
        iotElevatorRepairVo.setRecordList(recordVoList);
        IotElevatorFaultVo elevatorFaultVo = elevatorFaultService.queryByFaultCode(iotElevatorRepairVo.getFaultCode());
        iotElevatorRepairVo.setElevatorFaultVo(elevatorFaultVo);
        return iotElevatorRepairVo;
    }

    /**
     * 查询电梯维修列表
     */
    @Override
    public TableDataInfo<IotElevatorRepairVo> queryPageList(IotElevatorRepairBo bo, PageQuery pageQuery) {
        QueryWrapper<IotElevatorRepair> wrapper = Wrappers.query();
        if (StringUtils.equals(bo.getProcessState(), RepairStateEnum.WAIT_REPAIR.getCode())) {
            wrapper.in("er.process_state", RepairStateEnum.WAIT_REPAIR.getCode(), RepairStateEnum.WAIT_ACCEPT.getCode());
        } else {
            wrapper.eq(StringUtils.isNotBlank(bo.getProcessState()), "er.process_state", bo.getProcessState());
        }
        wrapper.eq(StringUtils.isNotBlank(bo.getIsOverhaul()), "ef.is_overhaul", bo.getIsOverhaul());
        Page<IotElevatorRepairVo> result = baseMapper.selectOwnVoPage(pageQuery.build(), wrapper);
        for (IotElevatorRepairVo record : result.getRecords()) {
            IotElevatorFaultVo elevatorFaultVo = elevatorFaultService.queryByFaultCode(record.getFaultCode());
            record.setElevatorFaultVo(elevatorFaultVo);
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询电梯维修列表
     */
    @Override
    public List<IotElevatorRepairVo> queryList(IotElevatorRepairBo bo) {
        LambdaQueryWrapper<IotElevatorRepair> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<IotElevatorRepair> buildQueryWrapper(IotElevatorRepairBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IotElevatorRepair> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getElevatorId() != null, IotElevatorRepair::getElevatorId, bo.getElevatorId());
        lqw.like(StringUtils.isNotBlank(bo.getElevatorName()), IotElevatorRepair::getElevatorName, bo.getElevatorName());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairCode()), IotElevatorRepair::getRepairCode, bo.getRepairCode());
        lqw.eq(StringUtils.isNotBlank(bo.getFaultCode()), IotElevatorRepair::getFaultCode, bo.getFaultCode());
        lqw.eq(bo.getStartDate() != null, IotElevatorRepair::getStartDate, bo.getStartDate());
        lqw.eq(StringUtils.isNotBlank(bo.getIsStopElevator()), IotElevatorRepair::getIsStopElevator, bo.getIsStopElevator());
        lqw.eq(bo.getSubmitDate() != null, IotElevatorRepair::getSubmitDate, bo.getSubmitDate());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairHours()), IotElevatorRepair::getRepairHours, bo.getRepairHours());
        lqw.eq(StringUtils.isNotBlank(bo.getReplaceParts()), IotElevatorRepair::getReplaceParts, bo.getReplaceParts());
        lqw.eq(StringUtils.isNotBlank(bo.getFaultReason()), IotElevatorRepair::getFaultReason, bo.getFaultReason());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairPlan()), IotElevatorRepair::getRepairPlan, bo.getRepairPlan());
        lqw.eq(bo.getRepairUserId() != null, IotElevatorRepair::getRepairUserId, bo.getRepairUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairPeople()), IotElevatorRepair::getRepairPeople, bo.getRepairPeople());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairImage()), IotElevatorRepair::getRepairImage, bo.getRepairImage());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairSign()), IotElevatorRepair::getRepairSign, bo.getRepairSign());
        lqw.eq(StringUtils.isNotBlank(bo.getDoneStatus()), IotElevatorRepair::getDoneStatus, bo.getDoneStatus());
        lqw.eq(bo.getProcessState() != null, IotElevatorRepair::getProcessState, bo.getProcessState());
        lqw.eq(StringUtils.isNotBlank(bo.getConfirmPeople()), IotElevatorRepair::getConfirmPeople, bo.getConfirmPeople());
        lqw.eq(bo.getConfirmDate() != null, IotElevatorRepair::getConfirmDate, bo.getConfirmDate());
        lqw.eq(StringUtils.isNotBlank(bo.getConfirmSign()), IotElevatorRepair::getConfirmSign, bo.getConfirmSign());
        lqw.eq(StringUtils.isNotBlank(bo.getScore()), IotElevatorRepair::getScore, bo.getScore());
        lqw.eq(StringUtils.isNotBlank(bo.getScoreContent()), IotElevatorRepair::getScoreContent, bo.getScoreContent());
        lqw.eq(StringUtils.isNotBlank(bo.getDispatchPeople()), IotElevatorRepair::getDispatchPeople, bo.getDispatchPeople());
        lqw.eq(bo.getDispatchDate() != null, IotElevatorRepair::getDispatchDate, bo.getDispatchDate());
        lqw.eq(StringUtils.isNotBlank(bo.getReportType()), IotElevatorRepair::getReportType, bo.getReportType());
        lqw.eq(StringUtils.isNotBlank(bo.getSubmitter()), IotElevatorRepair::getSubmitter, bo.getSubmitter());
        return lqw;
    }

    /**
     * 新增电梯维修
     */
    @Override
    public Boolean insertByBo(IotElevatorRepairBo bo) {
        IotElevatorRepair add = MapstructUtils.convert(bo, IotElevatorRepair.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setRepairId(add.getRepairId());
        }
        return flag;
    }

    /**
     * 修改电梯维修
     */
    @Override
    public Boolean updateByBo(IotElevatorRepairBo bo) {
        IotElevatorRepair update = MapstructUtils.convert(bo, IotElevatorRepair.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IotElevatorRepair entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除电梯维修
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 接受维修任务接口
     *
     * @param bo 维修ID
     * @return 结果
     */
    @Override
    public Boolean startRepair(IotElevatorRepairBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        IotElevatorRepairVo elevatorRepairVo = this.queryById(bo.getRepairId());
        //是否被别的工程师接取校验
        if (elevatorRepairVo.getRepairUserId() != null && !elevatorRepairVo.getRepairUserId().equals(loginUser.getUserId())) {
            throw new ServiceException("该维修已被其他工程师接取！");
        }
        //是否已接取任务
        if (elevatorRepairVo.getRepairUserId() == null) {
            IotFaultRecordBo faultRecordBo = new IotFaultRecordBo();
            //@TODO 存疑
            faultRecordBo.setFaultId(elevatorRepairVo.getRepairId());
            faultRecordBo.setTiringState("接受任务");
            faultRecordBo.setCreateTime(DateUtil.date());
            faultRecordBo.setRemark(loginUser.getNickname().concat("已赶往救援现场！"));
            faultRecordService.insertByBo(faultRecordBo);
        }
        //接受维修任务相关字段
        elevatorRepairVo.setRepairUserId(loginUser.getUserId());
        elevatorRepairVo.setRepairPeople(loginUser.getNickname());
        return this.updateByBo(BeanUtil.toBean(elevatorRepairVo, IotElevatorRepairBo.class));
    }

    /**
     * 根据故障单保存维修单
     *
     * @param elevatorFault 故障信息
     * @return
     */
    @Override
    public int saveElevatorRepairByFault(IotElevatorFaultBo elevatorFault) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        IotElevatorRepair elevatorRepair = BeanUtil.toBean(elevatorFault, IotElevatorRepair.class);
        elevatorRepair.setDispatchAvatar(loginUser.getAvatar());
        elevatorRepair.setDispatchPeople(loginUser.getNickname());
        elevatorRepair.setProcessState(RepairStateEnum.WAIT_ACCEPT.getCode());
        //维修单号
        elevatorRepair.setRepairCode(BusinessCodeEnum.REPAIR.getBusinessCode());
        //故障原因
        String business_fault_type = dictDataService.selectDictLabel("iot_fault_type", elevatorFault.getFaultType());
        elevatorRepair.setFaultReason(business_fault_type);
        elevatorRepair.setCreateTime(DateUtil.date());
        return baseMapper.insert(elevatorRepair);
    }

    /**
     * 上报故障
     *
     * @param elevatorFault 上报故障
     * @return 结果
     */
    @Override
    public Boolean reportFault(IotElevatorFaultBo elevatorFault) {
        IotElevatorVo iotElevatorVo = elevatorService.queryById(elevatorFault.getElevatorId());
        if (iotElevatorVo == null) {
            throw new ServiceException("电梯不存在");
        }
        LoginUser loginUser = LoginHelper.getLoginUser();
        //电梯名称
        elevatorFault.setElevatorName(iotElevatorVo.getElevatorName());
        //故障单号
        elevatorFault.setFaultCode(BusinessCodeEnum.FAULT.getBusinessCode());
        //上报类型
        elevatorFault.setReportType("0");//人工上报
        //上报时间
        elevatorFault.setReportTime(DateUtil.date());
        //处理状态
        elevatorFault.setDisposeState("1");
        elevatorFault.setDisposeMan(loginUser.getNickname());
        elevatorFault.setDisposeAvatar(loginUser.getAvatar());
        elevatorFault.setFaultMessage(elevatorFault.getFaultMessage());
        elevatorFault.setDisposeDate(DateUtil.date());
        elevatorFault.setDispatchDate(DateUtil.date());
        boolean save = elevatorFaultService.insertByBo(elevatorFault);
        //@TODO故障上报成功，发送消息给维修人员派单
        //故障转维修 -------------------------------------------------------------------------------------------------------------
        //添加保存维修单
        this.saveElevatorRepairByFault(elevatorFault);
        //更改小区、电梯状态
        if (iotElevatorVo.getStatus().equals(ElevatorStatusEnum.NORMAL.getCode())) {
            iotElevatorVo.setElevatorStatus(ElevatorStatusEnum.FAULT.getCode());
            elevatorService.updateByBo(BeanUtil.toBean(iotElevatorVo, IotElevatorBo.class));
        }
        WebSocketUtils.publishAll(iotElevatorVo.getElevatorName() + "发生故障！");
        return save;
    }

    /**
     * 开始维修工作
     *
     * @param faultRecord 故障记录
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean marchElevatorRepair(IotFaultRecordBo faultRecord) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        IotElevatorRepairVo iotElevatorRepairVo = this.queryById(faultRecord.getRepairId());
        //添加接受维修任务记录
//        if (StringUtils.isNull(faultRecord.getLatitude()) || StringUtils.isNull(faultRecord.getLongitude())) {
//            return error(Constants.UNVERIFY, "缺少维修人位置经纬度");
//        }

        faultRecord.setFaultId(faultRecord.getRepairId());
        faultRecord.setTiringState("到达现场");
        faultRecord.setCreateTime(DateUtil.date());
        faultRecord.setRemark(loginUser.getNickname().concat("已到达现场！"));
        faultRecordService.insertByBo(faultRecord);

        //开始维修任务相关字段
        iotElevatorRepairVo.setStartDate(DateUtil.date());
        iotElevatorRepairVo.setProcessState("1");
        //开始任务
        return this.updateByBo(BeanUtil.toBean(iotElevatorRepairVo, IotElevatorRepairBo.class));
    }

    /**
     * 提交维修信息 1.维修完成提交 2.经理审核
     *
     * @param elevatorRepair 电梯维修信息
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean submitElevatorRepair(IotElevatorRepairBo elevatorRepair) {
        IotElevatorRepairVo iotElevatorRepairVo = this.queryById(elevatorRepair.getRepairId());
        LoginUser loginUser = LoginHelper.getLoginUser();
        // 1.维修完成提交 2.经理审核
        if (elevatorRepair.getType().equals("1")) {
            //维修用时计算
            String repairHours = DateUtils.getDatePoor(iotElevatorRepairVo.getStartDate(), DateUtil.date());
            elevatorRepair.setRepairHours(repairHours);
            elevatorRepair.setDoneStatus("0");
            elevatorRepair.setSubmitDate(DateUtil.date());
            elevatorRepair.setProcessState(RepairStateEnum.REPAIRING.getCode());

            IotFaultRecordBo faultRecord = new IotFaultRecordBo();
            faultRecord.setFaultId(iotElevatorRepairVo.getRepairId());
            faultRecord.setTiringState("维修完成");
            faultRecord.setCreateTime(DateUtil.date());
            faultRecord.setRemark(loginUser.getNickname().concat("已完成维修工作！"));
            faultRecordService.insertByBo(faultRecord);
        } else if (elevatorRepair.getType().equals("2")) {
            //@TODO 判断是不是维保经理只有维保经理可以审批签字
            elevatorRepair.setConfirmPeople(loginUser.getNickname());
            elevatorRepair.setDoneStatus("1");
            elevatorRepair.setConfirmDate(DateUtil.date());
            //维修完成
            elevatorRepair.setProcessState(RepairStateEnum.FINISH.getCode());
        }
        //修改告警状态
        IotElevatorFaultVo elevatorFaultVo = iotElevatorRepairVo.getElevatorFaultVo();
        elevatorFaultVo.setDisposeState("4");
        elevatorFaultVo.setDisposeDate(new Date());//处理时间
        elevatorFaultVo.setFaultDuration(DateUtils.getDatePoor(iotElevatorRepairVo.getStartDate(), elevatorFaultVo.getReportTime()));//处理时长
        elevatorFaultService.updateByBo(BeanUtil.toBean(elevatorFaultVo, IotElevatorFaultBo.class));
        return this.updateByBo(elevatorRepair);
    }
}
